package com.qf.mod;


import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;

/**
 * 加密必须得保证数据安全性(解密后的数据正确性)
 *
 * java 是跨平台的语言, 一次编译处处运行 因为 jvm 虚拟机内部解释 java 代码是一样的逻辑 jvm 虚拟不是跨平台的
 *
 */

public class AESUtils {

    /**
     * 将二进制转换成16进制,加密后转字符串
     *
     * @param buf
     * @return
     */
    public static String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 将16进制转换为二进制 ,利用上面的转换方式转出的显示内容需要先利用此方式转码后解密用
     *
     * @param hexStr
     * @return
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }
   

    /**
     * 和 android 兼容的加密算法
     * 注意返回的 bute 数组不是一个合法的字符串对应的数组,不能直接转成字符串
     * @param value
     * @return
     */
    public static byte[] encryptNew(String value) {
        byte[] encrypted = null;
        try {
            byte[] raw = new byte[]{'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y'};//密码
            Key skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            byte[] iv = new byte[cipher.getBlockSize()];
            IvParameterSpec ivParams = new IvParameterSpec(iv);
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec,ivParams);
            encrypted  = cipher.doFinal(value.getBytes());
            System.out.println("encrypted string:" + encrypted.length);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return encrypted;
    }
    /**
     * 保证和移动端兼容,解密算法
     * 这个地方返回的数组就是原始字符串的 byte 数组
     * @param encrypted
     * @return
     */
    public static  byte[]  decryptNew(byte[] encrypted) {
        byte[] original = null;
        Cipher cipher = null;
        try {
            byte[] raw = new byte[]{'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y'};
            Key key = new SecretKeySpec(raw, "AES");
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            byte[] ivByte = new byte[cipher.getBlockSize()];
            IvParameterSpec ivParamsSpec = new IvParameterSpec(ivByte);
            cipher.init(Cipher.DECRYPT_MODE, key, ivParamsSpec);
            original= cipher.doFinal(encrypted);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return original;
    }

    public static void main(String[] args) {
        byte[] encryptNew = encryptNew("usertest");//加密成数组
        String s = parseByte2HexStr(encryptNew);//加密后的数组进行编码输出
        System.out.println(s);
        //服务端获取移动端传递过来的数据
        byte[] bytes = parseHexStr2Byte(s);//解码后的原始加密字符串
        byte[] bytes1 = decryptNew(bytes);//解密
        String string = new String(bytes1);//原始数据
        System.out.println(string);
    }
}
